// (c) Copyright 2013-2014 Stephen Gold <sgold@sonic.net>
// Distributed under the terms of the GNU General Public License

/*
 This file is part of the Bats Game.

 The Bats Game is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by the
 Free Software Foundation, either version 3 of the License, or (at your
 option) any later version.

 The Bats Game is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.

 You should have received a copy of the GNU General Public License
 along with the Bats Game.  If not, see <http://www.gnu.org/licenses/>.
 */
package bats.unit;

import com.jme3.animation.AnimChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
import jme3utilities.MyAnimation;
import jme3utilities.SimpleControl;

/**
 * A simple control to manage an oto's animations. It accepts two inputs:
 * setLaunchPhase() and setWalking(). It controls two AnimChannel, one for the
 * right arm and another for the rest of the skeleton.
 * <p>
 * Each instance is enabled at creation.
 *
 * @author Stephen Gold <sgold@sonic.net>
 */
public class OtoAnimationControl
        extends SimpleControl {
    // *************************************************************************
    // constants

    /**
     * message logger for this class
     */
    final private static Logger logger =
            Logger.getLogger(OtoAnimationControl.class.getName());
    // *************************************************************************
    // fields
    /**
     * animation channel for the whole skeleton except the right arm: set by
     * constructor
     */
    final private AnimChannel restOfBody;
    /**
     * animation channel for the right arm: set by constructor
     */
    final private AnimChannel rightArm;
    /**
     * if true, the walk animation is requested; if false, walk isn't requested
     */
    private boolean isWalking = false;
    /**
     * latest phase of the load/launch cycle (in seconds)
     */
    private float launchPhase = 0f;
    // *************************************************************************
    // constructors

    /**
     * Instantiate an enabled control for two specified animation channels.
     *
     * @param rightArm channel for animating the right arm (not null)
     * @param restOfBody channel for animating the rest of the body (not null)
     */
    public OtoAnimationControl(AnimChannel rightArm, AnimChannel restOfBody) {
        super();
        assert rightArm != null;
        this.rightArm = rightArm;

        assert restOfBody != null;
        this.restOfBody = restOfBody;

        assert isEnabled();
    }
    // *************************************************************************
    // new methods exposed

    /**
     * Accept a new request from LaunchControl.
     *
     * @param newPhase phase of the load/launch cycle (in seconds)
     */
    void setLaunchPhase(float newPhase) {
        if (launchPhase != newPhase) {
            logger.log(Level.INFO, "newPhase={0}", newPhase);
        }
        launchPhase = newPhase;
    }

    /**
     * Accept a new request from OtoControl.
     *
     * @param newState if true, play the walk animation, if not don't play it
     */
    public void setWalking(boolean newState) {
        isWalking = newState;
    }
    // *************************************************************************
    // SimpleControl methods

    /**
     * Callback invoked when the spatial's geometric state is about to be
     * updated, once per frame while attached and enabled.
     *
     * @param updateInterval time interval between updates (in seconds, &ge;0)
     */
    @Override
    protected void controlUpdate(float updateInterval) {
        super.controlUpdate(updateInterval);
        if (spatial == null) {
            return;
        }
        updateRightArm();
        updateRestOfBody();
    }
    // *************************************************************************
    // private methods

    /**
     * Update the animation of the rest of the body.
     */
    private void updateRestOfBody() {
        if (isWalking) {
            MyAnimation.blendTo(restOfBody, "Walk");
        } else {
            MyAnimation.blendTo(restOfBody, "stand");
        }
    }

    /**
     * Update the animation of the right arm.
     */
    private void updateRightArm() {
        if (launchPhase > 0f && launchPhase <= LaunchControl.launchPhase) {
            MyAnimation.blendTo(rightArm, "pull");
            if (launchPhase > LaunchControl.loadDuration) {
                rightArm.setSpeed(0f);
            } else {
                rightArm.setSpeed(1f);
            }
        } else {
            if (isWalking) {
                MyAnimation.blendTo(rightArm, "Walk");
            } else {
                MyAnimation.blendTo(rightArm, "stand");
            }
            rightArm.setSpeed(1f);
        }
    }
}